/* eslint-disable */
import { Decimal } from 'decimal.js'
import ScatterJS from '@scatterjs/core';
import ScatterTron from '@scatterjs/tron';
import TronWeb from 'tronweb';
import axios from 'axios'
import store from '@/store';
import Io from '@/utils/socket';
import { getReqUrl } from '../validate';

ScatterJS.plugins( new ScatterTron() );

// 获取登录状态最大次数
const maxFrequency = 100;
let nowFrequency = 0;

// 是否开启 Scatter 钱包
const hasScatter = false;

// axios.get(`https://apilist.tronscan.org/api/account?address=TLmutXucYfj6ehZBFh3gLzGSrBfYE3F7Ua`, {
//   timeout: 1000,
// }).then(() => true).catch(() => false)


// 节点配置
// let urlNode = 'https://httpapi.tronex.io';
// const env = process.env.NODE_ENV;
// switch (env) {
//   case 'development':
//   case 'tron':
//     urlNode = `http://${getReqUrl('ip')}:19090`;
//     break;
//   default:
//     break;
// }
// const fullNode = urlNode;
// const solidityNode = urlNode;
// const eventServer = `${urlNode}/`;

// const tronWebJs = new TronWeb(
//     fullNode,
//     solidityNode,
//     eventServer,
// );
// window.tronWebJs = tronWebJs;


class model {

  constructor() {
    this.vthis = null;
    this.scatter = null; // 登录、退出对象
    this.enuScatter = null; // 登录、退出对象
    this.scatterEosJs = null; // 登录后的各种操作对象
    this.tronWeb = null; // 波场对象
    this.tronWebState = {
      installed: false,
      loggedIn: false,
      from: 'TronLink'
    }; // 波场对象状态
    this.tronAccountAddress = null; // 波场账号地址
    this.chainName = null;
    this.priceDecimals = 10;
    this.env = process.env.NODE_ENV;
    // 配置
    this.EosJs = null;
    this.EosJsUse = null;
    this.BosJs = null;
    this.MeeJs = null;
    this.EnuJs = null;
    this.FibosJs = null;
    this.TelosJs = null;
    this.network = null;
    this.eosOptions = null;
    this.enuConnected = false;
  }

  scatterInit(vthis) {
    this.vthis = vthis;
    window.onload = this.tronWebGet(this);
  }

  // 获取tronWeb对象
  tronWebGet(v) {
    const self = v || this;
    self.tronWebState.installed = !!window.tronWeb;
    self.tronWebState.loggedIn = !!(window.tronWeb && window.tronWeb.ready);

    // 如果没有 window.tronWeb对象 获取scatter
    if (!self.tronWebState.installed && !self.tronWebState.loggedIn && hasScatter) {
      const network = ScatterJS.Network.fromJson(self.returnChainInfo('trx'));
      ScatterJS.connect('newpool.io', {network}).then(connected => {
        if(!connected) return;
        const httpProvider = new TronWeb.providers.HttpProvider(network.fullhost());
        let tron = new TronWeb(httpProvider, httpProvider, network.fullhost());
        tron.setDefaultBlock('latest');
        window.tronWeb = tron;
        self.tronWeb = window.tronWeb;
        self.tronWebState.installed = !!window.tronWeb;
        self.tronWebState.from = 'Scatter';
        const scatter = store.state.app.scatter;
        if (scatter && scatter.wallet === 'Scatter' && scatter.identity) {
          self.tronAccountAddress = scatter.identity.accounts[0].name;
          window.tronWeb.defaultAddress = {
            base58: self.tronAccountAddress,
            hex: window.tronWeb.address.toHex(self.tronAccountAddress),
            name: "",
            type: 1,
          }
          window.tronWeb.ready = true;
        }
      });
    }

    console.log(self.tronWebState);

    // 已获取tron对象
    if (self.tronWebState.installed && self.tronWebState.from === 'TronLink') {
      self.tronWeb = window.tronWeb;
      // 监听账户变化
      self.tronWeb.on('addressChanged', () => {
        // console.log('addressChanged')
        self.tronWebState = {
          installed: !!window.tronWeb,
          loggedIn: !!(window.tronWeb && window.tronWeb.ready),
          from: 'TronLink'
        };
        if(self.tronWebState.loggedIn) {
          self.tronAccountAddress = self.tronWeb.defaultAddress.base58;
          const scatter = store.state.app.scatter;
          if (scatter && scatter.identity
          && scatter.identity.accounts[0].name !== self.tronAccountAddress) {
            // 用户已切换
            self.getIdentity(() => {});
          }
        }
      });
    }
    // 已登录
    if(self.tronWebState.loggedIn && self.tronWebState.from === 'TronLink') {
      self.tronAccountAddress = self.tronWeb.defaultAddress.base58;
      const scatter = store.state.app.scatter;
      if (scatter && scatter.identity) {
        if (scatter.identity.accounts[0].name !== self.tronAccountAddress) {
          // 用户已切换
        }
        self.getIdentity(() => {});
      }
    }
    // 未登录
    if(!self.tronWebState.loggedIn) {
      nowFrequency += 1;
      if (nowFrequency > maxFrequency) return;
      // self.accountLoginOut(() => {});
      setTimeout(() => {
        this.tronWebGet(v)
      }, 1000);
    }
  }

  // 节点信息获取
  returnChainInfo(cname) {
    const chainName = cname.toLowerCase();
    const envobj = {};
    if (chainName === 'trx') {
      switch (this.env) {
        case 'development':
          envobj.blockchain = 'trx';
          envobj.host = getReqUrl('ip');
          envobj.port = 19090;
          envobj.protocol = 'http';
          envobj.chainId = '1';
          break;
        case 'production':
          envobj.blockchain = 'trx';
          envobj.host = 'api.trongrid.io';
          envobj.port = 443;
          envobj.protocol = 'https';
          envobj.chainId = '1';
          break;
        default:
          break;
      }
    }
    return envobj;
  }

  /*
  * 获取钱包身份
  * get scatter identityInfo => publicKey
  */
  getIdentity(callback) {
    if (this.tronWebState.from === 'TronLink') {
      if (!this.tronWebState.installed || !this.tronWebState.loggedIn) {
        this.tronWebGet();
      }
      if (!this.tronWebState.loggedIn) {
        this.vthis.$message.error(this.vthis.$t('error.locked'));
        callback('tronError');
        return;
      }
      this.tronWeb.trx.getAccount(this.tronAccountAddress).then((identity) => {
        // console.log('登录后的tronAccount');
        // console.log(identity);
        this.formatAccount(identity, 'TronLink', callback);
      }).catch((error) => {
        console.log(error); // eslint-disable-line
        this.vthis.$message.error(error.toString());
        callback(error);
      })
    }
    if (this.tronWebState.from === 'Scatter') {
      ScatterJS.logout().then(() => {
        ScatterJS.login().then(id => {
          if(!id) return console.error('no identity');
          const identity = ScatterJS.account('trx');
          window.tronWeb.ready = true;
          window.tronWeb.defaultAddress = {
            base58: identity.address,
            hex: window.tronWeb.address.toHex(identity.address),
            name: "",
            type: 1,
          }
          this.tronWeb = window.tronWeb;
          this.tronAccountAddress = this.tronWeb.defaultAddress.base58;
          this.tronWeb.trx.getAccount(this.tronAccountAddress).then((id) => {
            // console.log('Scatter登录后的tronAccount');
            // console.log(id);
            this.formatAccount(id, 'Scatter', callback);
          }).catch((error) => {
            console.log(error); // eslint-disable-line
            this.vthis.$message.error(error.toString());
            callback(error);
          })
        });
      });
    }
  }

  // 登录后格式化/存储用户
  formatAccount(identity, wallet, callback) {
    let address = this.tronAccountAddress;
    address = `${address.substring(0, 5)}...${address.substring(address.length - 5, address.length)}`;
    const scatterItem = store.state.app.scatter;
    scatterItem.labelName = null;
    if (identity.account_name) {
      // 16进制转字符串 解析自定义用户名
      let labname = this.tronWeb.toUtf8(identity.account_name);
      if (labname.length > 12) {
        labname = `${labname.substring(0, 12)}...`;
      }
      scatterItem.labelName = labname;
    }
    const hasJh = identity.balance === undefined;
    scatterItem.identity = {
      accounts: [{
        // authority: !hasJh ? (identity.active_permission[0] && identity.active_permission[0].permission_name) : 'active',
        authority: 'active',
        balance: !hasJh ? this.tronWeb.fromSun(identity.balance) : 0,
        name: this.tronAccountAddress,
        nameFormat: address,
        blockchain: 'tron',
        publicKey: this.tronWeb.defaultAddress.hex,
      }],
    }
    scatterItem.wallet = wallet;
    scatterItem.chain = 'tron';
    scatterItem.update = new Date().getTime();
    // console.log("scatterItem.update");
    // console.log(scatterItem.update);
    store.dispatch('setScatter', scatterItem);
    Io.accountBind(this.tronAccountAddress);
    localStorage.setItem('Frontend-Token', '');
    const back = {
      code: 'success'
    }
    callback(back);
  }

  // 退出账户
  accountLoginOut(callback) {
    let scat = store.state.app.scatter;
    if (scat && scat.identity && scat.wallet === 'Scatter') {
      try {
        ScatterJS.logout().then(() => {
          this.storeAccountOut(scat);
        });
      } catch (error) {
        this.storeAccountOut(scat);
      }
      return;
    }
    if (scat && scat.identity) {
      this.storeAccountOut(scat);
      return;
    }
    callback();
  }

  // 退出账户信息置为空
  storeAccountOut(scat) {
    // console.log('退出 -- storeAccountOut');
    if (scat && scat.identity) {
      Io.accountOut(this.tronAccountAddress);
      scat.wallet = '';
      scat.identity = null;
      scat.chain = 'tron';
      scat.online = false;
      scat.labelName = null;
      localStorage.setItem('Frontend-Token', '');
      this.accountByScatter = null;
      // console.log(scat);
      scat.update = new Date().getTime();
      store.dispatch('setScatter', scat);
    }
  }

  /*
  * 签名
  */
  arbitrarySignature(vthis, timestamp, callback) {
    if (!this.tronWeb) return;
    this.vthis = vthis;
    const account = store.state.app.scatter.identity.accounts[0];
    const publicKey = account.publicKey;
    let data = `${timestamp}`;
    data = this.tronWeb.toHex(data);
    console.log(this.tronWeb);
    this.tronWeb.trx.signMessage(data).then((signature) => {
      const back = {
        signature,
        account: account.name,
        timestamp,
        timestampToHex: data,
        type: 'web'
      }
      callback(back);
    }).catch((error) => {
      console.log(error);
      this.vthis.$message.error(error);
      // callback(error);
    });
  }

  /*
  * 投票操作
  */
  async transactionBuilderVote(obj, callback) {
    const votes = obj.votes; // { address: voteCount }
    const address = this.tronAccountAddress;
    console.log(obj);
    try {
      const rr = await this.tronWeb.transactionBuilder.vote(votes, address, 1);
      const sign = await this.tronWeb.trx.sign(rr);
      const result = await this.tronWeb.trx.sendRawTransaction(sign);
      callback(result);
    } catch (error) {
      callback(error);
    }
  }

  /*
  * 获取投票信息
  */
  async VoteInfo(obj, callback) {
    const address = obj.account || this.tronAccountAddress;
    if (!address) return;
    const back = {
      allVote: 0, // 总投票数
      votedCount: 0, // 已投票总数
      votedCountForNewdex: 0, // 给newdex已投票总数
      canVote: 0, // 可投票数
      voteList: [], // 投票列表
      trxBalance: 0,
    }
    try {
      const info = await this.tronWeb.trx.getAccount(address);
      back.trxBalance = this.tronWeb.fromSun(info.balance);
      back.voteList = info.votes || [];
      back.voteList.forEach((v) => {
        // 已投票总数
        back.votedCount += v.vote_count;
        if (v.vote_address === this.tronWeb.address.toHex(obj.newdexVoteAccount)) {
          back.votedCountForNewdex = v.vote_count;
        }
      });
      // 自己给别人冻结
      const allEnergyToOther = Number(this.tronWeb.fromSun(info.account_resource.delegated_frozen_balance_for_energy || 0));
      const allBandwidthToOther = Number(this.tronWeb.fromSun(info.delegated_frozen_balance_for_bandwidth || 0));
      // 自己给自己冻结
      const bandwidth = info.frozen;
      let bandwidthNumber = 0;
      if (bandwidth && bandwidth.length > 0) {
        bandwidthNumber = Number(this.tronWeb.fromSun(bandwidth[0].frozen_balance));
      }
      let energyNumber = 0;
      if (info.account_resource) {
        const energy = info.account_resource.frozen_balance_for_energy || 0;
        energyNumber = Number(this.tronWeb.fromSun(energy.frozen_balance));
      }
      // 总投票数
      back.allVote = allEnergyToOther + allBandwidthToOther + bandwidthNumber + energyNumber;
      // 可投票数 = 总投票数 - 已投票总数
      back.canVote = back.allVote - back.votedCount;
      callback(back);
    } catch (error) {
      callback(back);
    }
  }



  /*
  * 转账/交易 操作
  */
  async tronTransaction(obj, callback) {
    const remarks = JSON.parse(obj.remarks);
    const dexContract = await this.tronWeb.contract().at(obj.toAccount);
    const dex = obj.trad.b;
    obj.price = !obj.price || obj.price === 'NaN' ? 1 : obj.price;
    obj.count = !obj.count || obj.count === 'NaN' ? 10 ** obj.trad.coinDecimal : obj.count;
    obj.amount = !obj.amount || obj.amount === 'NaN' ? 10 ** obj.trad.valuationCoinDecimal : obj.amount;
    obj.memo = `channel:${remarks.channel},ref:${store.state.app.scatter.wallet}`;
    const priceDev = 10 ** this.priceDecimals;
    obj.price = Number(Decimal.mul(obj.price, priceDev).toString());
    console.log(obj);
    const isUsdtTrx = obj.trad.b.name === 'USDT' && obj.trad.a.name === 'TRX';
    const isUsdtOther = obj.trad.b.name === 'USDT' && obj.trad.a.name !== 'TRX';
    if (dex.trc === 'trc10') {
      if (remarks.type === 'buy-limit' || remarks.type === 'buy-market') { // 买入
        if (isUsdtOther) {
          this.buyTrc10UsdtToken(obj, remarks, dexContract, callback);
          return;
        }
        this.buyTrc10Token(obj, remarks, dexContract, callback);
      }
      if (remarks.type === 'sell-limit' || remarks.type === 'sell-market') { // 卖出
        if (isUsdtOther) {
          this.sellTrc10UsdtToken(obj, remarks, dexContract, callback);
          return;
        }
        this.sellTrc10Token(obj, remarks, dexContract, callback)
      }
    }
    
    if (dex.trc === 'trc20') {
      if (remarks.type === 'buy-limit' || remarks.type === 'buy-market') { // 买入
        if (isUsdtTrx) {
          this.buyTrxOrder(obj, remarks, dexContract, callback)
          return;
        }
        if (isUsdtOther) {
          this.buyTrc20UsdtToken(obj, remarks, dexContract, callback);
          return;
        }
        this.buyTrc20Order(obj, remarks, dexContract, callback);
      }
      if (remarks.type === 'sell-limit' || remarks.type === 'sell-market') { // 卖出
        if (isUsdtTrx) {
          this.sellTrxOrder(obj, remarks, dexContract, callback)
          return;
        }
        if (isUsdtOther) {
          this.sellTrc20UsdtToken(obj, remarks, dexContract, callback);
          return;
        }
        this.sellTrc20Order(obj, remarks, dexContract, callback)
      }
    }
  }
  // trx为计价币 买入trc10
  async buyTrc10Token(obj, remarks, dexContract, callback) {
    // console.log('trx为计价币 买入trc10');
    try {
      const result = await dexContract.buyToken(obj.code, obj.count, obj.price, remarks.type, obj.memo).send({
        // shouldPollResponse: true,
        feeLimit: 1000000,
        callValue: this.tronWeb.toSun(obj.quantity)
      });
      this.callbackTron(result, callback)
    } catch (error) {
      this.callbackTron(error, callback)
    }
  }
  // trx为计价币 卖出trc10
  async sellTrc10Token(obj, remarks, dexContract, callback) {
    // console.log('trx为计价币 卖出trc10');
    try {
      const result = await dexContract.sellToken(obj.price, remarks.type, obj.memo).send({
        // shouldPollResponse: true,
        feeLimit: 1000000,
        tokenId: obj.trad.b.code,
        tokenValue: obj.count,
      })
      this.callbackTron(result, callback)
    } catch (error) {
      this.callbackTron(error, callback)
    }
  }
  // trx为计价币 买入trc20
  async buyTrc20Order(obj, remarks, dexContract, callback) {
    // console.log('trx为计价币 买入trc20');
    try {
      const result = await dexContract.buyOrder(obj.code, obj.count, obj.price, remarks.type, obj.memo).send({
        // shouldPollResponse: true,
        feeLimit: 1000000,
        callValue: this.tronWeb.toSun(obj.quantity)
      })
      this.callbackTron(result, callback)
    } catch (error) {
      this.callbackTron(error, callback)
    }
  }
  // trx为计价币 卖出trc20
  async sellTrc20Order(obj, remarks, dexContract, callback) {
    // console.log('trx为计价币 卖出trc20');
    try {
      const contract = await this.tronWeb.contract().at(obj.trad.b.code);
      await contract.approve(obj.toAccount, obj.count).send({
          // shouldPollResponse: true,
          feeLimit: 1000000,
          callValue: 0
      });
      const result = await dexContract.sellOrder(obj.trad.b.code, obj.count, obj.price, remarks.type, obj.memo).send({
        // shouldPollResponse: true,
        feeLimit: 1000000,
        callValue: 0
      })
      this.callbackTron(result, callback);
    } catch (error) {
      this.callbackTron(error, callback);
    }
  }

  // 用USDT买入TRX
  async buyTrxOrder(obj, remarks, dexContract, callback) {
    // console.log('用USDT买入TRX');
    try {
      const contract = await this.tronWeb.contract().at(obj.trad.a.code);
      await contract.approve(obj.toAccount, obj.amount).send({
          // shouldPollResponse: true,
          feeLimit: 1000000,
          callValue: 0
      });
      const result = await dexContract.buyTrx(tronWeb.address.fromHex(obj.trad.a.code), obj.amount, obj.price, remarks.type, obj.memo).send({
        // shouldPollResponse: true,
        feeLimit: 1000000,
        callValue: 0
      })
      this.callbackTron(result, callback);
    } catch (error) {
      this.callbackTron(error, callback);
    }
  }

  // 卖出TRX 换 USDT
  async sellTrxOrder(obj, remarks, dexContract, callback) {
    // console.log('卖出TRX 换 USDT');
    try {
      const result = await dexContract.sellTrx(obj.code, obj.count, obj.price, remarks.type, obj.memo).send({
        // shouldPollResponse: true,
        feeLimit: 1000000,
        callValue: this.tronWeb.toSun(obj.quantity)
      })
      this.callbackTron(result, callback)
    } catch (error) {
      this.callbackTron(error, callback)
    }
  }

  // usdt为计价币 买入trc10币种
  async buyTrc10UsdtToken(obj, remarks, dexContract, callback) {
    // const quantityAmount = Number(Decimal.mul(obj.amount, 10 ** obj.trad.valuationCoinDecimal).toString());
    // obj.amount = quantityAmount;
    console.log('usdt为计价币 买入trc10币种');
    console.log('approve');
    console.log(obj.toAccount, obj.amount);
    console.log('buyTrc10UsdtToken');
    console.log(
      obj.trad.a.code,
      obj.trad.b.code,
      obj.amount,
      obj.count,
      obj.price,
      remarks.type,
      obj.memo);
    try {
      const contract = await this.tronWeb.contract().at(obj.trad.a.code);
      await contract.approve(obj.toAccount, obj.amount).send({
        feeLimit: 1e6,
        // shouldPollResponse: true,
        callValue: 0
      });
      const result = await dexContract.trc20BuyToken(
        obj.trad.a.code,
        obj.trad.b.code,
        obj.amount,
        obj.count,
        obj.price,
        remarks.type,
        obj.memo).send({
        // shouldPollResponse: true,
        feeLimit: 1000000,
        callValue: 0
      })
      this.callbackTron(result, callback);
    } catch (error) {
      this.callbackTron(error, callback);
    }
  }

  // usdt为计价币 卖出trc10币种
  async sellTrc10UsdtToken(obj, remarks, dexContract, callback) {
    // console.log('usdt为计价币 卖出trc10币种');
    try {
      const result = await dexContract.trc20SellToken(
        obj.trad.a.code,
        obj.trad.b.code,
        obj.amount,
        obj.count,
        obj.price,
        remarks.type,
        obj.memo).send({
        // shouldPollResponse: true,
        feeLimit: 1000000,
        tokenId: obj.trad.b.code,
        tokenValue: obj.count,
      })
      this.callbackTron(result, callback)
    } catch (error) {
      this.callbackTron(error, callback)
    }
  }

  // usdt为计价币 买入trc20币种
  async buyTrc20UsdtToken(obj, remarks, dexContract, callback) {
    console.log('usdt为计价币 买入trc20币种', obj.amount);
    // const quantityAmount = Number(Decimal.mul(obj.amount, 10 ** obj.trad.valuationCoinDecimal).toString());
    // obj.amount = quantityAmount;
    console.log('approve');
    console.log(obj.toAccount, obj.amount);
    console.log('trc20Buy');
    console.log(
      obj.trad.a.code,
      obj.trad.b.code,
      obj.amount,
      obj.count,
      obj.price,
      remarks.type,
      obj.memo)
    try {
      const contract = await this.tronWeb.contract().at(obj.trad.a.code);
      await contract.approve(obj.toAccount, obj.amount).send({
          // shouldPollResponse: true,
          feeLimit: 1e6,
          callValue: 0
      });
      const result = await dexContract.trc20Buy(
        obj.trad.a.code,
        obj.trad.b.code,
        obj.amount,
        obj.count,
        obj.price,
        remarks.type,
        obj.memo).send(
        {
          // shouldPollResponse: true,
          feeLimit: 1e6,
          callValue: 0
        })
      this.callbackTron(result, callback);
    } catch (error) {
      this.callbackTron(error, callback);
    }
  }

  // usdt为计价币 卖出trc20币种
  async sellTrc20UsdtToken(obj, remarks, dexContract, callback) {
    // console.log('usdt为计价币 卖出trc20币种');
    try {
      const contract = await this.tronWeb.contract().at(obj.trad.b.code);
      await contract.approve(obj.toAccount, obj.count).send({
          // shouldPollResponse: true,
          feeLimit: 1000000,
          callValue: 0
      });
      const result = await dexContract.trc20Sell(
        tronWeb.address.fromHex(obj.trad.a.code),
        tronWeb.address.fromHex(obj.trad.b.code),
        obj.amount,
        obj.count,
        obj.price,
        remarks.type,
        obj.memo).send(
        {
          // shouldPollResponse: true,
          feeLimit: 1000000,
          callValue: 0
        })
      this.callbackTron(result, callback);
    } catch (error) {
      this.callbackTron(error, callback);
    }
  }

  // tron sell /buy callback
  callbackTron(result, callback) {
    console.log(result);
    if (result && result.length === 0) {
      callback({ processed: true })
      return;
    }
    const back = {
      code: '500',
      error: {
        code: '500',
      },
      message: result.error || 'Unknown error, please try again.',
      details: result
    }
    callback(back);
  }

  /* 合约撤单 操作 */
  async eosOrderCancel(obj, callback) {
    const dexContract = await this.tronWeb.contract().at(obj.toAccount);
    const response = await dexContract.cancelOrder(obj.chainOrderId).send({
      shouldPollResponse: true,
      feeLimit: 1000000,
      callValue: 0
    })
    this.callbackTron(response, callback);
  }

  /*
  * 获取余额
  */
  async getTronBalance(address, way) {
    const blance = {
      trx: 0,
      other: 0,
    }
    try {
      if (way === 'trx') {
        const balance = await this.tronWeb.trx.getBalance(this.tronAccountAddress);
        blance.trx = this.tronWeb.fromSun(balance)
      }
      if (way === 'trc20') {
        const contract = await this.tronWeb.contract().at(address);
        blance.other = 0;
        if (contract && contract.balanceOf) {
          const balanceOf = await contract.balanceOf(this.tronAccountAddress).call();
          let balance = balanceOf * 1;
          if (isNaN(balance)) {
            balance = balanceOf.balance * 1;
          }
          if (isNaN(balance)) {
            balance = 0
          }
          const decimal = await contract.decimals().call();
          if (decimal) {
            blance.other = Number(balance) / 10 ** decimal;
          } else {
            blance.other = Number(balance)
          }
        }
      }
      if (way === 'trc10') {
        const identity = await this.tronWeb.trx.getAccount(this.tronAccountAddress);
        blance.other = 0;
        if (identity.assetV2) {
          const has = identity.assetV2.find(v => v.key.toString() === address.toString());
          if (has) {
            const byid = await this.tronWeb.trx.getTokenByID(address);
            if (byid.precision) {
              blance.other = has.value / 10 ** byid.precision;
            } else {
              blance.other = has.value;
            }
          }
        }
      }
      return blance;
    } catch (error) {
      blance.error = error;
      return blance
    }
  }

  // 获取账户资源信息
  async getAccountResources(callback) {
    if (!this.tronWeb) return;
    const result = await this.tronWeb.trx.getAccountResources(this.tronAccountAddress);
    if (result && result.freeNetLimit) {
      const back = {
        net: { // 宽带
          total: (result.NetLimit || 0) + (result.freeNetLimit || 0), // 宽带总量 = 抵押总量 + 免费送
          used: (result.NetUsed|| 0) + (result.freeNetUsed || 0),
          free: result.freeNetLimit, // 免费送的
        },
        energy: { // 能量
          total: result.EnergyLimit || 0,
          used: result.EnergyUsed || 0,
        }
      }
      back.net.sy = back.net.total - back.net.used; // 宽带剩余量
      back.energy.sy = back.energy.total - back.energy.used; // 能量剩余量
      callback(back);
      return;
    }
    callback('error');
  }

  // 账户名更改
  updateAccount(obj, callback) {
    this.tronWeb.trx.updateAccount(obj.account).then((res) => {
      this.vthis.$message.error(res);
      callback('success');
      const scatterItem = store.state.app.scatter;
      let labname = obj.account;
      if (labname.length > 12) {
        labname = `${labname.substring(0, 12)}...`;
      }
      scatterItem.labelName = labname;
      scatterItem.update = new Date().getTime();
      store.dispatch('setScatter', scatterItem);
    }).catch((error) => {
      this.vthis.$message.error(error);
      callback(error);
    });
  }

  /*
  * 冻结trx获取资源
  * @param amount 要冻结的 TRX (在 SUN 中) 的数量
  * @param duration 冻结 TRX 的天数。至少 3 天
  * @param resource 你为了获得而冻结 TRX 的资源。必须是 “BANDWIDTH（带宽）” 或 “ENERGY（能量）”。
  * @param address（可选） 要冻结的 TRX 所有者的地址（默认为呼叫者的默认地址）
  */
  async freezeBalance(obj, callback) {
    let resource = 'BANDWIDTH'; // “BANDWIDTH（带宽）” 或 “ENERGY（能量）”,
    if (obj.resource) {
      resource = 'ENERGY';
    }
    
    const amount = this.tronWeb.toSun(obj.amount);
    const address = this.tronAccountAddress;
    let receiver = address;
    if (!obj.address) {
      obj.address = address;
    }
    if (obj.address !== this.tronAccountAddress) {
      receiver = obj.address;
    }
    console.log(obj);
    try {
      const rr = await this.tronWeb.transactionBuilder.freezeBalance(amount, 3, resource, address, receiver);
      const sign = await this.tronWeb.trx.sign(rr);
      const result = await this.tronWeb.trx.sendRawTransaction(sign);
      callback(result);
    } catch (error) {
      callback(error);
    }
  }

  /*
  * 解冻trx资源
  * @param resource 你为了获得而冻结 TRX 的资源。必须是 “BANDWIDTH（带宽）” 或 “ENERGY（能量）”。
  * @param address 要解冻的 TRX 所有者的地址
  */
  async unfreezeBalance(obj, callback) {
    let resource = 'BANDWIDTH'; // “BANDWIDTH（带宽）” 或 “ENERGY（能量）”,
    if (obj.resource) {
      resource = 'ENERGY';
    }
    if (!obj.address) {
      obj.address = this.tronAccountAddress;
    }
    if (!obj.receiver) {
      obj.receiver = obj.address;
    }
    try {
      const rr = await this.tronWeb.transactionBuilder.unfreezeBalance(resource, obj.address, obj.receiver);
      const sign = await this.tronWeb.trx.sign(rr);
      const result = await this.tronWeb.trx.sendRawTransaction(sign);
      callback(result);
    } catch (error) {
      callback(error);
    }
  }

  // 获取冻结列表
  async freeznList(callback) {
    const back = {
      meToAther: [], // 我给别人冻结的
      atherToMe: [], // 别人给我冻结的
      allBandwidthFromOther: 0, // 别人给我抵押的总带宽
      allEnergyForOther: 0, // 别人给我抵押的总能量
      
      allBandwidthToOther: 0, // 我给别人抵押的总带宽
      allEnergyToOther: 0, // 我给别人抵押的总能量

      meToMeBandwidth: { // 自己给自己的宽带冻结
        expire_time: 0,
        frozen_balance: 0
      },
      meToMeEnergy: { // 自己给自己的能量冻结
        expire_time: 0,
        frozen_balance: 0
      },
    }
    const result = await axios.get(`https://apilist.tronscan.org/api/account?address=${this.tronAccountAddress}`);
    if (result.status === 200) {
      const data = result.data;
      const delegated = data.delegated;
      if (delegated && delegated.sentDelegatedBandwidth.length > 0) {
        // 宽带
        delegated.sentDelegatedBandwidth.forEach((v) => {
          const item = {
            type: 'bandwidth', // 宽带
            tiem: v.expire_time_for_bandwidth,
            from: v.from,
            to: v.to,
            number: this.tronWeb.fromSun(v.frozen_balance_for_bandwidth)
          }
          back.meToAther.push(item)
        })
      }
      if (delegated && delegated.sentDelegatedResource.length > 0) {
        // 能量
        delegated.sentDelegatedResource.forEach((v) => {
          const item = {
            type: 'energy', // 能量
            tiem: v.expire_time_for_energy,
            from: v.from,
            to: v.to,
            number: this.tronWeb.fromSun(v.frozen_balance_for_energy)
          }
          back.meToAther.push(item)
        })
      }
      if (delegated && delegated.receivedDelegatedBandwidth.length > 0) {
        // 宽带
        delegated.receivedDelegatedBandwidth.forEach((v) => {
          const item = {
            type: 'bandwidth', // 宽带
            tiem: v.expire_time_for_bandwidth,
            from: v.from,
            to: v.to,
            number: this.tronWeb.fromSun(v.frozen_balance_for_bandwidth)
          }
          back.atherToMe.push(item)
        })
      }
      if (delegated && delegated.receivedDelegatedResource.length > 0) {
        // 能量
        delegated.receivedDelegatedResource.forEach((v) => {
          const item = {
            type: 'energy', // 能量
            tiem: v.expire_time_for_energy,
            from: v.from,
            to: v.to,
            number: this.tronWeb.fromSun(v.frozen_balance_for_energy)
          }
          back.atherToMe.push(item)
        })
      }
    }
    const firme = await this.tronWeb.trx.getUnconfirmedAccount(this.tronAccountAddress);
    if (firme && firme.account_resource) {
      back.allEnergyForOther = this.tronWeb.fromSun(firme.account_resource.acquired_delegated_frozen_balance_for_energy || 0);
      back.allEnergyToOther = this.tronWeb.fromSun(firme.account_resource.delegated_frozen_balance_for_energy || 0);
      const energy = firme.account_resource.frozen_balance_for_energy;
      if (energy) {
        back.meToMeEnergy = {
          expire_time: energy.expire_time,
          frozen_balance: this.tronWeb.fromSun(energy.frozen_balance)
        }
      }
    }
    if (firme) {
      back.allBandwidthFromOther = this.tronWeb.fromSun(firme.acquired_delegated_frozen_balance_for_bandwidth || 0);
      back.allBandwidthToOther = this.tronWeb.fromSun(firme.delegated_frozen_balance_for_bandwidth || 0);
      //自己给自己冻结
      const bandwidth = firme.frozen;
      if (bandwidth && bandwidth.length > 0) {
        back.meToMeBandwidth = {
          expire_time: bandwidth[0].expire_time,
          frozen_balance: this.tronWeb.fromSun(bandwidth[0].frozen_balance)
        }
      }
    }
    callback(back);
  }

  /*
  * 获取订单条数
  */
  getTableRowsForOrders(callback) {
    callback(null);
  }

  // scatter操作回调
  handleScatterErrorBack(res) {
    console.log('Error');
    console.log(res);
    if (res.code || res.error) {
      let code = res.code;
      if (code === 500 && res.error) {
        code = res.error.code;
      }
      if (res.error && res.error.details && res.error.details.length > 0
        && code !== 3080001
        && code !== 3080002
        && code !== 3080004
        && code !== 3040005) {
        const errorDetails = res.error.details[0].message.split(':')[1] || res.error.details[0].message;
        this.vthis.$message.error(`${errorDetails}【${code}】`);
        return;
      }
      switch (code) {
        case 3080001:
          this.vthis.$message.error(`${this.vthis.$t('error.error3080001')}【${code}】`);
          break;
        case 3080002:
          this.vthis.$message.error(`${this.vthis.$t('error.error3080002')}【${code}】`);
          break;
        case 3080004:
          this.vthis.$message.error(`${this.vthis.$t('error.error3080004')}【${code}】`);
          break;
        case 3040005:
          this.vthis.$message.error(`${this.vthis.$t('error.error3040005')}【${code}】`);
          break;
        case 3050003:
          this.vthis.$message.error(`${this.vthis.$t('error.error3050003')}【${code}】`);
          break;
        default:
          this.vthis.$message.error(`${res.message} 【${code}】`);
          break;
      }
      return;
    }
    this.vthis.$message.error(`Unknow Error!【${res}】`);
  }

  //  catch 错误回调
  errorCall(e, callback) {
    const self = this;
    const scatapp = store.state.app.scatter;
    console.log('error callback', typeof(e), e); // eslint-disable-line
    let back = {
      code: 100001,
      error: {
        code: 100001
      },
      message: 'Unknown anomaly',
    };
    if (typeof (e) === 'object') {
      back = {
        code: '402',
        error: {
          code: '402',
        },
        message: e.message || 'Privileges have been lost. Please log in again.',
      }
      if (e.code === 402) {
        back.message = e.message;
      }
      if (e.code === 'Scatter') {
        // ${this.vthis.$t('error.error3040005')}
        back.code = '100002'
        back.message = this.vthis.$t('public.scatterDesktop');
      }
      if (e.Error && typeof (e.Error) === 'string' && e.Error.indexOf('No Identity') >= 0) {
        back.message = 'Privileges have been lost. Please log in again.';
        // self.accountLoginOut(() => {
        //   self.getIdentity(self.vthis, () => {});
        // });
      }
      if (scatapp && scatapp.identity && !scatterConnected) {
        self.initNext();
      }
      if (e.name === "AssertionError") {
        back.code = '500';
        back.message = e.message;
      }
    }
    if (typeof (e) === 'string') {
      if (e.indexOf('code') >= 0) {
        back = JSON.parse(e);
      } else {
        back = {
          code: '0002',
          error: {
            code: '0002',
          },
          message: 'Failed to get the balance',
        }
      }
    }
    callback(back);
  }
}

export const TronModel = new model()